home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / Direct3D / EffectEdit / RenderView.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-27  |  58.0 KB  |  1,640 lines

  1. // RenderView.cpp : implementation of the CRenderView class
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "EffectEdit.h"
  6.  
  7. #include "EffectDoc.h"
  8. #include "UIElements.h"
  9. #include "RenderView.h"
  10.  
  11. #ifdef _DEBUG
  12. #define new DEBUG_NEW
  13. #undef THIS_FILE
  14. static char THIS_FILE[] = __FILE__;
  15. #endif
  16.  
  17. // Custom vertex type for the flat-texture background
  18. struct FLATBACKGROUNDVERTEX
  19. {
  20.     float x,y,z,w;
  21.     float u,v;
  22.  
  23.     static const DWORD FVF;
  24. };
  25. const DWORD FLATBACKGROUNDVERTEX::FVF = D3DFVF_XYZRHW | D3DFVF_TEX1;
  26.  
  27.  
  28. // Custom vertex type for the cubemap-texture background
  29. struct CUBEBACKGROUNDVERTEX
  30.     float x,y,z; 
  31.     float u,v,w; 
  32.  
  33.     static const DWORD FVF;
  34. };
  35. const DWORD CUBEBACKGROUNDVERTEX::FVF = D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0);
  36.  
  37. /////////////////////////////////////////////////////////////////////////////
  38. // CRenderView
  39.  
  40. static CRenderView* s_pRenderView = NULL;
  41.  
  42.  
  43. IMPLEMENT_DYNCREATE(CRenderView, CFormView)
  44.  
  45. BEGIN_MESSAGE_MAP(CRenderView, CFormView)
  46.     //{{AFX_MSG_MAP(CRenderView)
  47.     ON_WM_DESTROY()
  48.     ON_WM_SIZE()
  49.     ON_COMMAND(ID_VIEW_RENDER, OnRender)
  50.     //}}AFX_MSG_MAP
  51. END_MESSAGE_MAP()
  52.  
  53. /////////////////////////////////////////////////////////////////////////////
  54. // CRenderView construction/destruction
  55.  
  56. CRenderView::CRenderView()
  57.     : CFormView(CRenderView::IDD)
  58. {
  59.     //{{AFX_DATA_INIT(CRenderView)
  60.         // NOTE: the ClassWizard will add member initialization here
  61.     //}}AFX_DATA_INIT
  62.     // TODO: add construction code here
  63.     m_bShowStats = TRUE;
  64.     m_pFont = NULL;
  65.     m_pEffect = NULL;
  66.     m_pTextSprite = NULL;
  67.     m_pBackgroundTexture = NULL;
  68.     m_pEnvironmentTexture = NULL;
  69.     m_dwBackgroundColor = D3DCOLOR_ARGB(0, 0, 0, 255);
  70.     m_pVBBackground = NULL;
  71.     m_iTechnique = -1;
  72.     m_iPass = -1;
  73.     m_strMesh[0] = 0;
  74.     m_pMesh = NULL;
  75.     m_pbufMaterials = NULL;
  76.     m_dwNumMaterials = 0;
  77.     m_ppTextures = NULL;
  78.     m_strBackgroundTexture[0] = 0;
  79.     m_vObjectCenter = D3DXVECTOR3(0, 0, 0);
  80.     m_fObjectRadius = 1.0f;
  81.     m_pMeshSphere = NULL;
  82.     m_bWireframe = FALSE;
  83.     m_bNoTextures = FALSE;
  84.     m_bSelectedPassOnly = FALSE;
  85.     m_bUpToSelectedPassOnly = FALSE;
  86.     m_bUINeedsReset = TRUE;
  87. }
  88.  
  89. CRenderView::~CRenderView()
  90. {
  91.     SAFE_RELEASE( m_pEffect );
  92.     DXUTShutdown();
  93. }
  94.  
  95. void CRenderView::DoDataExchange(CDataExchange* pDX)
  96. {
  97.     CFormView::DoDataExchange(pDX);
  98.     //{{AFX_DATA_MAP(CRenderView)
  99.         // NOTE: the ClassWizard will add DDX and DDV calls here
  100.     //}}AFX_DATA_MAP
  101. }
  102.  
  103. BOOL CRenderView::PreCreateWindow(CREATESTRUCT& cs)
  104. {
  105.     // TODO: Modify the Window class or styles here by modifying
  106.     //  the CREATESTRUCT cs
  107.  
  108.     return CFormView::PreCreateWindow(cs);
  109. }
  110.  
  111.  
  112. // DXUT Callbacks
  113. void CRenderView::OnFrameMoveCB( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  114. {
  115.     if( s_pRenderView )
  116.         s_pRenderView->OnFrameMove( pd3dDevice, fTime, fElapsedTime );
  117. }
  118.  
  119.  
  120. void CRenderView::OnFrameRenderCB( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  121. {
  122.     if( s_pRenderView )
  123.         s_pRenderView->OnFrameRender( pd3dDevice, fTime, fElapsedTime );
  124. }
  125.  
  126.  
  127. HRESULT CRenderView::OnCreateDeviceCB( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  128. {
  129.     if( s_pRenderView )
  130.         return s_pRenderView->OnCreateDevice( pd3dDevice, pBackBufferSurfaceDesc );
  131.     return S_OK;
  132. }
  133.  
  134.  
  135. HRESULT CRenderView::OnResetDeviceCB( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  136. {
  137.     if( s_pRenderView )
  138.         return s_pRenderView->OnResetDevice( pd3dDevice, pBackBufferSurfaceDesc );
  139.     return S_OK;
  140. }
  141.  
  142.  
  143. void CRenderView::OnLostDeviceCB()
  144. {
  145.     if( s_pRenderView )
  146.         s_pRenderView->OnLostDevice();
  147. }
  148.  
  149.  
  150. void CRenderView::OnDestroyDeviceCB()
  151. {
  152.     if( s_pRenderView )
  153.         s_pRenderView->OnDestroyDevice();
  154. }
  155.  
  156.  
  157. //-----------------------------------------------------------------------------
  158. // Name: FullScreenWndProc()
  159. // Desc: The WndProc funtion used when the app is in fullscreen mode. This is
  160. //       needed simply to trap the ESC key.
  161. //-----------------------------------------------------------------------------
  162. LRESULT CALLBACK FullScreenWndProc( HWND hWnd, UINT msg, WPARAM wParam,
  163.                                     LPARAM lParam )
  164. {
  165.     if( msg == WM_CREATE )
  166.     {
  167.         s_pRenderView = (CRenderView*)((CREATESTRUCT*)lParam)->lpCreateParams;
  168.     }
  169.     else if( msg == WM_CLOSE )
  170.     {
  171.         // User wants to exit, so go back to windowed mode and exit for real
  172.         s_pRenderView->OnToggleFullscreen();
  173.         s_pRenderView->GetActiveWindow()->PostMessage( WM_CLOSE, 0, 0 );
  174.         //g_App.GetMainWnd()->PostMessage( WM_CLOSE, 0, 0 );
  175.     }
  176.     else if( msg == WM_SETCURSOR )
  177.     {
  178.         SetCursor( NULL );
  179.     }
  180.     else if( ( msg == WM_KEYUP && wParam == VK_ESCAPE ) ||
  181.              ( msg == WM_SYSCHAR && wParam == VK_RETURN ) )
  182.     {
  183.         // User wants to leave fullscreen mode
  184.         s_pRenderView->OnToggleFullscreen();
  185.         return 0;
  186.     }
  187.     else if ( msg == WM_LBUTTONDOWN ||
  188.               msg == WM_LBUTTONUP ||
  189.               msg == WM_RBUTTONDOWN ||
  190.               msg == WM_RBUTTONUP ||
  191.               msg == WM_MOUSEMOVE )
  192.     {
  193.         // Map the coordinates from fullscreen window to
  194.         // RenderView window.
  195.         POINT pt = { GET_X_LPARAM( lParam ), GET_Y_LPARAM( lParam ) };
  196.         ::MapWindowPoints( hWnd, s_pRenderView->GetSafeHwnd(), &pt, 1 );
  197.         lParam = MAKELPARAM( pt.x, pt.y );
  198.  
  199.         // forward mouse messages to the render view window
  200.         s_pRenderView->PostMessage( msg, wParam, lParam );
  201.     }
  202.  
  203.     return DefWindowProc( hWnd, msg, wParam, lParam );
  204. }
  205.  
  206.  
  207. void CRenderView::OnInitialUpdate()
  208. {
  209.     CFormView::OnInitialUpdate();
  210.     GetParentFrame()->RecalcLayout();
  211.     ResizeParentToFit();
  212.  
  213.     // Save static reference to the render window
  214.     m_hwndRenderWindow = GetDlgItem(IDC_RENDERWINDOW)->GetSafeHwnd();
  215.  
  216.     // Register a class for a fullscreen window
  217.     WNDCLASS wndClass = { CS_HREDRAW | CS_VREDRAW, FullScreenWndProc, 0, 0, NULL,
  218.                           NULL, LoadCursor(NULL, IDC_ARROW), (HBRUSH)GetStockObject(WHITE_BRUSH), NULL,
  219.                           _T("Fullscreen Window") };
  220.     RegisterClass( &wndClass );
  221.  
  222.     // We create the fullscreen window (not visible) at startup, so it can
  223.     // be the focus window.  The focus window can only be set at CreateDevice
  224.     // time, not in a Reset, so ToggleFullscreen wouldn't work unless we have
  225.     // already set up the fullscreen focus window.
  226.     m_hwndRenderFullScreen = CreateWindow( _T("Fullscreen Window"), NULL,
  227.                                            WS_POPUP, 0, 0, 100, 100,
  228.                                            GetTopLevelParent()->GetSafeHwnd(), 0L, NULL, this );
  229.  
  230.     // If we haven't initialized the D3D framework, do so now
  231.     if( !DXUTGetD3DDevice() )
  232.     {
  233.         CRect rc;
  234.         ::GetClientRect( m_hwndRenderWindow, &rc );
  235.         if( rc.Width() == 0 || rc.Height() == 0 )
  236.         {
  237.             MessageBox( TEXT("The render view must be visible when EffectEdit starts.  Please change the window size or splitters and start EffectEdit again."),
  238.                 TEXT("EffectEdit") );
  239.         }
  240.         else
  241.         {
  242.             // Set up the DXUT callbacks
  243.             DXUTSetCallbackDeviceCreated( OnCreateDeviceCB );
  244.             DXUTSetCallbackDeviceReset( OnResetDeviceCB );
  245.             DXUTSetCallbackDeviceLost( OnLostDeviceCB );
  246.             DXUTSetCallbackDeviceDestroyed( OnDestroyDeviceCB );
  247.             DXUTSetCallbackFrameRender( OnFrameRenderCB );
  248.             DXUTSetCallbackFrameMove( OnFrameMoveCB );
  249.  
  250.             // Show the cursor and clip it when in full screen
  251.             DXUTSetCursorSettings( true, true );
  252.  
  253.             DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
  254.  
  255.             // Note that for the MFC samples, the device window and focus window
  256.             // are not the same.
  257.             DXUTSetWindow( m_hwndRenderFullScreen, m_hwndRenderFullScreen, m_hwndRenderWindow, false );
  258.             ::GetClientRect( m_hwndRenderWindow, &m_rcWindowClient );
  259.             HRESULT hr = DXUTCreateDevice( D3DADAPTER_DEFAULT, true, m_rcWindowClient.right - m_rcWindowClient.left,
  260.                                            m_rcWindowClient.bottom - m_rcWindowClient.top, NULL, NULL );
  261.             if( FAILED( hr ) )
  262.             {
  263.                 // If D3D is not functional, do not continue.  End the application now.
  264.                 CFrameWnd *pTop = this->GetTopLevelFrame();
  265.                 if( pTop )
  266.                     pTop->PostMessage( WM_CLOSE, 0, 0 );
  267.             }
  268.         }
  269.     }
  270.     GetDocument()->Compile();
  271. }
  272.  
  273. /////////////////////////////////////////////////////////////////////////////
  274. // CRenderView diagnostics
  275.  
  276. #ifdef _DEBUG
  277. void CRenderView::AssertValid() const
  278. {
  279.     CFormView::AssertValid();
  280. }
  281.  
  282.  
  283. void CRenderView::Dump(CDumpContext& dc) const
  284. {
  285.     CFormView::Dump(dc);
  286. }
  287.  
  288.  
  289. CEffectDoc* CRenderView::GetDocument() // non-debug version is inline
  290. {
  291.     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CEffectDoc)));
  292.     return (CEffectDoc*)m_pDocument;
  293. }
  294. #endif //_DEBUG
  295.  
  296.  
  297. void CRenderView::OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  298. {
  299.      // Setup world matrix
  300.     D3DXMatrixTranslation( &m_matWorld, -m_vObjectCenter.x,
  301.                                       -m_vObjectCenter.y,
  302.                                       -m_vObjectCenter.z );
  303.     D3DXMatrixMultiply( &m_matWorld, &m_matWorld, m_ArcBallMesh.GetRotationMatrix() );
  304.     D3DXMatrixMultiply( &m_matWorld, &m_matWorld, m_ArcBallMesh.GetTranslationMatrix() );
  305.     pd3dDevice->SetTransform( D3DTS_WORLD, &m_matWorld );
  306.  
  307.     D3DXVECTOR3 vFrom( 0, 0, -2*m_fObjectRadius );
  308.     D3DXVECTOR3 vAt( 0, 0, 0 );
  309.     D3DXVECTOR3 vUp( 0, 1, 0 );
  310.     D3DXMatrixLookAtLH( &m_matView, &vFrom, &vAt, &vUp );
  311.     D3DXMatrixMultiply( &m_matView, m_ArcBallView.GetRotationMatrix(), &m_matView );
  312.     D3DXMatrixMultiply( &m_matView, &m_matView, m_ArcBallView.GetTranslationMatrix() );
  313.     pd3dDevice->SetTransform( D3DTS_VIEW, &m_matView );
  314.     
  315.     m_UIElements.SetMatView( &m_matView );
  316.     m_UIElements.SetObjectRadius( m_fObjectRadius );
  317. }
  318.  
  319. // Vertex data for a cube that is used to draw the environment
  320. //   3D Positon and 3D texture coordinate for lookup in cube map
  321. static CUBEBACKGROUNDVERTEX EnvironmentVerts[] =
  322. {
  323.     { 1.0f,  1.0f, 1.0f, 1.0f, 1.0f, 1.0f},
  324.     { 1.0f,  1.0f,-1.0f, 1.0f, 1.0f,-1.0f},
  325.     { 1.0f, -1.0f, 1.0f, 1.0f,-1.0f, 1.0f},
  326.     { 1.0f, -1.0f,-1.0f, 1.0f,-1.0f,-1.0f},
  327.     {-1.0f,  1.0f, 1.0f,-1.0f, 1.0f, 1.0f},
  328.     {-1.0f,  1.0f,-1.0f,-1.0f, 1.0f,-1.0f},
  329.     {-1.0f, -1.0f, 1.0f,-1.0f,-1.0f, 1.0f},
  330.     {-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f},
  331. };
  332.  
  333. //  index data for the cube to draw the environment with
  334. static WORD EnvironmentIndices[] =
  335. {
  336.     0, 1, 3,  0, 3, 2,   4, 7, 5,  4, 6, 7,
  337.     0, 2, 6,  0, 6, 4,   1, 7, 3,  1, 5, 7,
  338.     0, 5, 1,  0, 4, 5,   2, 3, 7,  2, 7, 6
  339. };
  340.  
  341. void CRenderView::OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  342. {
  343.     HRESULT hr;
  344.  
  345.     // Clear the viewport
  346.     pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
  347.                        m_dwBackgroundColor, 1.0f, 0L );
  348.     if( SUCCEEDED( hr = pd3dDevice->BeginScene() ) )
  349.     {
  350.         if( m_pEffect != NULL )
  351.         {
  352.             if (m_pEnvironmentTexture != NULL)
  353.             {
  354.                 // set the rotation of the environment
  355.                 // Note: EffectEdit always shows the environment cubemap aligned with world
  356.                 // space (world matrix is identity), but some apps might want to support
  357.                 // a rotated cubemap.
  358.                 D3DXMATRIXA16 matWorldEnvMap;
  359.                 D3DXMatrixIdentity(&matWorldEnvMap);
  360.                 pd3dDevice->SetTransform( D3DTS_WORLD, &matWorldEnvMap);
  361.                 pd3dDevice->SetTransform( D3DTS_VIEW, m_ArcBallView.GetRotationMatrix() );
  362.  
  363.                 // Render background image
  364.                 pd3dDevice->SetTexture(0, m_pEnvironmentTexture);
  365.                 pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
  366.                 pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID);
  367.                 pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  368.                 pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  369.                 pd3dDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
  370.  
  371.                 pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  372.                 pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  373.                 pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  374.                 pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  375.  
  376.                 pd3dDevice->SetFVF( CUBEBACKGROUNDVERTEX::FVF);
  377.                 pd3dDevice->DrawIndexedPrimitiveUP( D3DPT_TRIANGLELIST, 0, 8, 12, EnvironmentIndices, 
  378.                     D3DFMT_INDEX16, EnvironmentVerts, sizeof(CUBEBACKGROUNDVERTEX));
  379.                 
  380.                 // restore the device state
  381.                 pd3dDevice->SetTexture(0, NULL);
  382.                 pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE);
  383.                 pd3dDevice->SetTransform( D3DTS_WORLD, &m_matWorld );
  384.                 pd3dDevice->SetTransform( D3DTS_VIEW, &m_matView );
  385.             }
  386.             else if( m_pBackgroundTexture != NULL )
  387.             {
  388.                 // Render background image
  389.                 pd3dDevice->SetTexture(0, m_pBackgroundTexture);
  390.                 pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
  391.                 pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
  392.                 pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  393.                 pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  394.  
  395.                 pd3dDevice->SetFVF( FLATBACKGROUNDVERTEX::FVF);
  396.                 pd3dDevice->SetStreamSource( 0, m_pVBBackground, 0, 6*sizeof(float) );
  397.                 pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
  398.                 
  399.                 pd3dDevice->SetTexture(0, NULL);
  400.                 pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
  401.             }
  402.  
  403.             // Render the mesh with the current effect
  404.             if( m_pEffect != NULL )
  405.             {
  406.                 if( m_MatWorldEffectHandle != NULL )
  407.                     m_pEffect->SetMatrix( m_MatWorldEffectHandle, &m_matWorld );
  408.  
  409.                 if( m_MatViewEffectHandle != NULL )
  410.                     m_pEffect->SetMatrix( m_MatViewEffectHandle, &m_matView );
  411.  
  412.                 if( m_MatProjEffectHandle != NULL )
  413.                     m_pEffect->SetMatrix( m_MatProjEffectHandle, &m_matProj );
  414.  
  415.                 if( m_MatWorldViewEffectHandle != NULL )
  416.                 {
  417.                     D3DXMATRIX matWorldView = m_matWorld * m_matView;
  418.                     m_pEffect->SetMatrix( m_MatWorldViewEffectHandle, &matWorldView );
  419.                 }
  420.  
  421.                 if( m_MatViewProjEffectHandle != NULL )
  422.                 {
  423.                     D3DXMATRIX matViewProj = m_matView * m_matProj;
  424.                     m_pEffect->SetMatrix( m_MatViewProjEffectHandle, &matViewProj );
  425.                 }
  426.  
  427.                 if( m_MatWorldViewProjEffectHandle != NULL )
  428.                 {
  429.                     D3DXMATRIX matWorldViewProj = m_matWorld * m_matView * m_matProj;
  430.                     m_pEffect->SetMatrix( m_MatWorldViewProjEffectHandle, &matWorldViewProj );
  431.                 }
  432.  
  433.                 if( m_VecCameraPosEffectHandle != NULL )
  434.                 {
  435.                     D3DXMATRIXA16 matViewInv;
  436.                     D3DXMatrixInverse( &matViewInv, NULL, &m_matView );
  437.                     D3DXVECTOR4 vecPosition( matViewInv._41, matViewInv._42, matViewInv._43, 1.0f );
  438.                     m_pEffect->SetVector( m_VecCameraPosEffectHandle, &vecPosition );
  439.                 }
  440.  
  441.                 if( m_TimeEffectHandle != NULL )
  442.                     m_pEffect->SetFloat( m_TimeEffectHandle, float(fTime) );
  443.  
  444.                 if( m_MeshRadiusEffectHandle != NULL )
  445.                     m_pEffect->SetFloat( m_MeshRadiusEffectHandle, m_fObjectRadius );
  446.  
  447.                 m_UIElements.SetEffectParameters( m_pEffect );
  448.  
  449.                 D3DCAPS9 d3dCaps;
  450.                 pd3dDevice->GetDeviceCaps( &d3dCaps );
  451.  
  452.                 UINT numPasses;
  453.                 hr = m_pEffect->Begin( &numPasses, 0 );
  454.  
  455.                 if( SUCCEEDED( hr ) )
  456.                 {
  457.                     for( UINT iPass = 0; iPass < numPasses; iPass++ )
  458.                     {
  459.                         if( m_bSelectedPassOnly )
  460.                             iPass = m_iPass;
  461.  
  462.                         hr = m_pEffect->BeginPass( iPass );
  463.                         
  464.                         if( m_bWireframe )
  465.                             pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );
  466.                         else
  467.                             pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
  468.                         
  469.                         if( m_bNoTextures )
  470.                         {
  471.                             for( UINT iStage = 0; iStage < d3dCaps.MaxTextureBlendStages; iStage++ )
  472.                                 pd3dDevice->SetTexture( iStage, NULL );
  473.                         }
  474.  
  475.                         if( m_pMesh == NULL )
  476.                         {
  477.                             m_pMeshSphere->DrawSubset( 0 );
  478.                         }
  479.                         else
  480.                         {
  481.                             for( UINT i = 0; i < m_dwNumMaterials; i++ )
  482.                             {
  483.                                 if( m_MaterialAmbientEffectHandle != NULL )
  484.                                     m_pEffect->SetVector( m_MaterialAmbientEffectHandle, (LPD3DXVECTOR4)&m_pMaterials[i].MatD3D.Ambient );
  485.                                 if( m_MaterialDiffuseEffectHandle != NULL )
  486.                                     m_pEffect->SetVector( m_MaterialDiffuseEffectHandle, (LPD3DXVECTOR4)&m_pMaterials[i].MatD3D.Diffuse );
  487.                                 if( m_MaterialSpecularEffectHandle != NULL )
  488.                                     m_pEffect->SetVector( m_MaterialSpecularEffectHandle, (LPD3DXVECTOR4)&m_pMaterials[i].MatD3D.Specular );
  489.                                 if( m_MaterialSpecularPowerEffectHandle != NULL )
  490.                                     m_pEffect->SetFloat( m_MaterialSpecularPowerEffectHandle, m_pMaterials[i].MatD3D.Power );
  491.                                 m_pEffect->CommitChanges();                           
  492.                                 m_pMesh->DrawSubset( i );
  493.                             }
  494.                         }
  495.  
  496.                         hr = m_pEffect->EndPass();
  497.  
  498.                         if( m_bSelectedPassOnly || ( m_bUpToSelectedPassOnly && (int)iPass == m_iPass ) )
  499.                             break;
  500.                     }
  501.  
  502.                     hr = m_pEffect->End();
  503.                 }
  504.  
  505.                 // Render the UI objects
  506.                 m_UIElements.Render( pd3dDevice );
  507.  
  508.             }
  509.  
  510.         }
  511.  
  512.         if( m_bShowStats )
  513.         {
  514.             CDXUTTextHelper txtHelper( m_pFont, m_pTextSprite, 15 );
  515.  
  516.             txtHelper.Begin();
  517.             // Output statistics
  518.             txtHelper.SetInsertionPos( 5, 5 );
  519.             txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
  520.             txtHelper.DrawTextLine( DXUTGetFrameStats() );
  521.             txtHelper.DrawTextLine( DXUTGetDeviceStats() );
  522.             if( m_pEffect == NULL )
  523.             {
  524.                 txtHelper.SetForegroundColor( D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f ) );
  525.                 txtHelper.DrawTextLine( L"Error in effect file" );
  526.             }
  527.  
  528.             if( !m_bTechniqueValidValid )
  529.             {
  530.                 m_bTechniqueValid = SUCCEEDED( m_pEffect->ValidateTechnique( m_pEffect->GetCurrentTechnique() ) );
  531.                 m_bTechniqueValidValid = TRUE;
  532.             }
  533.  
  534.             if( !m_bTechniqueValid )
  535.             {
  536.                 txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f ) );
  537.                 txtHelper.SetInsertionPos( 2, 45 );
  538.                 txtHelper.DrawTextLine( L"Warning: technique not valid with current device settings" );
  539.             }
  540.  
  541.             if( !((CEffectEditApp*)AfxGetApp())->AppActivated() )
  542.             {
  543.                 txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
  544.                 txtHelper.SetInsertionPos( 2, 60 );
  545.                 txtHelper.DrawTextLine( L"Note: sleeping between frames because app is not frontmost, fps may be lower" );
  546.             }
  547.  
  548.             txtHelper.End();
  549.         }
  550.         // End the scene.
  551.         pd3dDevice->EndScene();
  552.     }
  553. }
  554.  
  555.  
  556. /////////////////////////////////////////////////////////////////////////////
  557. // CRenderView message handlers
  558.  
  559. void CRenderView::OnDestroy()
  560. {
  561.     ::DestroyWindow( m_hwndRenderFullScreen );
  562. }
  563.  
  564.  
  565. void CRenderView::OnSize(UINT nType, int cx, int cy) 
  566. {
  567.     SetScrollSizes( MM_TEXT, CSize(cx, cy) );
  568.  
  569.     CFormView::OnSize(nType, cx, cy);
  570.     
  571.     CWnd* pGroup = GetDlgItem(IDC_GROUPBOX);
  572.     CWnd* pRenderWnd = GetDlgItem(IDC_RENDERWINDOW);
  573.     CWnd* pRenderText = GetDlgItem(IDC_RENDERTEXT);
  574.  
  575.     if( pGroup != NULL && 
  576.         pRenderWnd != NULL &&
  577.         pRenderText != NULL )
  578.     {
  579.         CRect rc;
  580.         INT textHeight;
  581.         pRenderText->GetClientRect(&rc);
  582.         textHeight = rc.Height();
  583.  
  584.         pRenderText->SetWindowPos(NULL, 0, cy - textHeight - 5, cx, textHeight, SWP_NOZORDER);
  585.         pRenderText->Invalidate();
  586.         pGroup->SetWindowPos(NULL, 7, 2, cx - 7 - 4, cy - textHeight - 2 - 10, SWP_NOZORDER);
  587.  
  588.         pGroup->GetClientRect(&rc);
  589.         pGroup->MapWindowPoints(this, &rc);
  590.  
  591.  
  592.         RECT rcClientOld = m_rcWindowClient;
  593.         
  594.         rc.InflateRect( -10, -17, -10, -10 );
  595.         pRenderWnd->SetWindowPos(NULL, rc.left, rc.top, rc.Width(), rc.Height(), SWP_NOZORDER);
  596.  
  597.         if( DXUTGetD3DDevice() != NULL )
  598.         {
  599.             pRenderWnd->GetClientRect( &m_rcWindowClient );
  600.             DXUTStaticWndProc( GetSafeHwnd(), WM_SIZE, nType, MAKELPARAM( cx, cy ) );
  601.             DXUTStaticWndProc( GetSafeHwnd(), WM_EXITSIZEMOVE, 0, 0 );
  602.         }
  603.     }
  604. }
  605.  
  606.  
  607. void CRenderView::OnRender() 
  608. {
  609.     if( DXUTGetD3DDevice() != NULL )
  610.         DXUTRender3DEnvironment();
  611. }
  612.  
  613.  
  614. HRESULT CRenderView::OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  615. {
  616.     HRESULT hr;
  617.  
  618.     // Initialize the font
  619.     if( FAILED( hr = D3DXCreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, 
  620.                                      OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
  621.                                      _T("Arial"), &m_pFont ) ) )
  622.         return hr;
  623.  
  624.     if( FAILED( hr = D3DXCreateSphere( pd3dDevice, 1.0f, 40, 40, &m_pMeshSphere, NULL ) ) )
  625.         return hr;
  626.  
  627.     if( FAILED( hr = m_UIElements.OnCreateDevice( pd3dDevice ) ) )
  628.         return hr;
  629.  
  630.     if( GetDocument()->GetCode().GetLength() > 0 )
  631.         GetDocument()->Compile( true );
  632.  
  633.     return S_OK;
  634. }
  635.  
  636. void CRenderView::OnDestroyDevice()
  637. {
  638.     SAFE_RELEASE( m_pFont );
  639.     SAFE_RELEASE( m_pBackgroundTexture );
  640.     SAFE_RELEASE( m_pEnvironmentTexture );
  641.     SAFE_RELEASE( m_pMeshSphere );
  642.     m_UIElements.OnDestroyDevice();
  643.     UnloadMesh();
  644.     SAFE_RELEASE( m_pEffect );
  645. }
  646.  
  647.  
  648. HRESULT CRenderView::OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  649. {
  650.     HRESULT hr;
  651.  
  652.     if( FAILED( hr = m_pFont->OnResetDevice() ) )
  653.         return hr;
  654.  
  655.     // Create a sprite to help batch calls when drawing many lines of text
  656.     if( FAILED( hr = D3DXCreateSprite( pd3dDevice, &m_pTextSprite ) ) )
  657.         return hr;
  658.  
  659.     if( FAILED( hr = m_UIElements.OnResetDevice( pd3dDevice ) ) )
  660.         return hr;
  661.  
  662.     // Build background image vertex buffer
  663.     if ( FAILED( hr = pd3dDevice->CreateVertexBuffer( sizeof(FLATBACKGROUNDVERTEX)*4, 0,
  664.         FLATBACKGROUNDVERTEX::FVF, D3DPOOL_MANAGED, &m_pVBBackground, NULL ) ) )
  665.     {
  666.         return hr;
  667.     }
  668.  
  669.     //set up a set of points which represents the screen
  670.     static struct { float x,y,z,w; float u,v; } s_Verts[] =
  671.     {
  672.         {750.0f,  -0.5f, 0.5f, 1.0f, 1,0},
  673.         {750.0f, 750.0f, 0.5f, 1.0f, 1,1},
  674.         { -0.5f,  -0.5f, 0.5f, 1.0f, 0,0},
  675.         { -0.5f, 750.0f, 0.5f, 1.0f, 0,1},
  676.     };
  677.  
  678.     s_Verts[0].x = (float)pBackBufferSurfaceDesc->Width - 0.5f;
  679.     s_Verts[1].x = (float)pBackBufferSurfaceDesc->Width - 0.5f;
  680.     s_Verts[1].y = (float)pBackBufferSurfaceDesc->Height - 0.5f;
  681.     s_Verts[3].y = (float)pBackBufferSurfaceDesc->Height - 0.5f; 
  682.  
  683.     //copy them into the buffer
  684.     void *pVerts;
  685.     if ( FAILED(hr = m_pVBBackground->Lock( 0, sizeof(s_Verts), (void**)&pVerts, 0 )) )
  686.         return hr;
  687.  
  688.     memcpy( pVerts, s_Verts, sizeof(s_Verts) );
  689.  
  690.     m_pVBBackground->Unlock();
  691.  
  692.     if( m_pEffect != NULL )
  693.         m_pEffect->OnResetDevice();
  694.  
  695.     // Setup the arcball parameters
  696.     m_ArcBallMesh.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height, 0.85f );
  697.     m_ArcBallView.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height, 0.85f );
  698.  
  699.     // Setup the projection matrix
  700.     FLOAT      fAspect = (FLOAT)pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height;
  701.     D3DXMatrixPerspectiveFovLH( &m_matProj, D3DX_PI/4, fAspect, 
  702.                                 m_fObjectRadius/64.0f, m_fObjectRadius*64.0f );
  703.     pd3dDevice->SetTransform( D3DTS_PROJECTION, &m_matProj );
  704.  
  705.     m_UIElements.SetInfo( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height, &m_matProj );
  706.  
  707.     return S_OK;
  708. }
  709.  
  710.  
  711. void CRenderView::OnLostDevice()
  712. {
  713.     m_pFont->OnLostDevice();
  714.  
  715.     m_UIElements.OnLostDevice();
  716.  
  717.     SAFE_RELEASE( m_pVBBackground );
  718.  
  719.     if( m_pEffect != NULL )
  720.         m_pEffect->OnLostDevice();
  721.  
  722.     SAFE_RELEASE( m_pTextSprite );
  723. }
  724.  
  725.  
  726. // Helper class for D3DXCreateEffect() to be able to load include files
  727. class CIncludeManager : public ID3DXInclude
  728. {
  729. protected:
  730.     CRenderView* m_pView;
  731.  
  732. public:
  733.     CIncludeManager( CRenderView* pView ) { m_pView = pView; }
  734.     STDMETHOD(Open)(D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes);
  735.     STDMETHOD(Close)(LPCVOID pData);
  736. };
  737.  
  738.  
  739. HRESULT CIncludeManager::Open(D3DXINCLUDE_TYPE IncludeType, LPCSTR pName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes)
  740. {
  741.     CFile f;
  742.     WCHAR strFile[MAX_PATH];
  743.     WCHAR strFileFull[MAX_PATH];
  744.  
  745.     MultiByteToWideChar( CP_ACP, 0, pName, -1, strFile, MAX_PATH );
  746.  
  747.     if( FAILED( m_pView->EE_FindMediaFileCch( strFileFull, MAX_PATH, strFile ) ) )
  748.         return E_FAIL;
  749.  
  750.     if( !f.Open( strFileFull, CFile::modeRead ) ) 
  751.         return E_FAIL;
  752.  
  753.     UINT size = (UINT)f.GetLength();
  754.  
  755.     BYTE* pData = new BYTE[size];
  756.     if( pData == NULL )
  757.         return E_OUTOFMEMORY;
  758.  
  759.     f.Read( pData, size );
  760.  
  761.     *ppData = pData;
  762.     *pBytes = size;
  763.  
  764.     return S_OK;
  765. }
  766.  
  767.  
  768. HRESULT CIncludeManager::Close(LPCVOID pData)
  769. {
  770.     BYTE* pData2 = (BYTE*)pData;
  771.     SAFE_DELETE_ARRAY( pData2 );
  772.     return S_OK;
  773. }
  774.  
  775.  
  776. HRESULT CRenderView::CompileEffect(CString strEffect, BOOL bUseShaderOptimizations, BOOL bFromFile, CString &strErrors, 
  777.                                    CStringList& techniqueNameList, int* piTechnique, BOOL* pbTryLater)
  778. {
  779.     HRESULT hr = S_OK;
  780.     LPD3DXBUFFER pBufferErrors = NULL;
  781.     CIncludeManager includeManager(this);
  782.  
  783.     *pbTryLater = FALSE;
  784.  
  785.     if( DXUTGetD3DDevice() == NULL )
  786.     {
  787.         *pbTryLater = TRUE;
  788.         return E_FAIL;
  789.     }
  790.  
  791.     SAFE_RELEASE( m_pEffect );
  792.     m_MatWorldEffectHandle = NULL;
  793.     m_MatViewEffectHandle = NULL;
  794.     m_MatProjEffectHandle = NULL;
  795.     m_MatWorldViewEffectHandle = NULL;
  796.     m_MatViewProjEffectHandle = NULL;
  797.     m_MatWorldViewProjEffectHandle = NULL;
  798.     m_VecCameraPosEffectHandle = NULL;
  799.     m_MaterialAmbientEffectHandle = NULL;
  800.     m_MaterialDiffuseEffectHandle = NULL;
  801.     m_MaterialSpecularEffectHandle = NULL;
  802.     m_MaterialSpecularPowerEffectHandle = NULL;
  803.     m_TimeEffectHandle = NULL;
  804.     m_MeshRadiusEffectHandle = NULL;
  805.  
  806.     if( m_bUINeedsReset )
  807.     {
  808.         m_UIElements.DeleteAllElements();
  809.         ResetCamera();
  810.         UnloadMesh();
  811.         m_fObjectRadius = 1.0f;
  812.         m_vObjectCenter.x = 0;
  813.         m_vObjectCenter.y = 0;
  814.         m_vObjectCenter.z = 0;
  815.         // Adjust near/far clip planes of projection matrix based on the object radius
  816.         const D3DSURFACE_DESC *pBackBufferDesc = DXUTGetBackBufferSurfaceDesc();
  817.         FLOAT fAspect = (FLOAT)pBackBufferDesc->Width / (FLOAT)pBackBufferDesc->Height;
  818.         D3DXMatrixPerspectiveFovLH( &m_matProj, D3DX_PI/4, fAspect, 
  819.                                     m_fObjectRadius/64.0f, m_fObjectRadius*64.0f );
  820.         DXUTGetD3DDevice()->SetTransform( D3DTS_PROJECTION, &m_matProj );
  821.         m_bUINeedsReset = FALSE;
  822.     }
  823.     else
  824.     {
  825.         // Delete all effect handles inside UI elements, but keep their other state
  826.         m_UIElements.DeleteEffectObjects();
  827.     }
  828.  
  829.     techniqueNameList.RemoveAll();
  830.     GetDlgItem(IDC_RENDERTEXT)->SetWindowText( TEXT("(nothing to render)") );
  831.  
  832.     DWORD dwFlags = D3DXSHADER_DEBUG;
  833.     if( !bUseShaderOptimizations )
  834.         dwFlags |= D3DXSHADER_SKIPOPTIMIZATION;
  835.  
  836.     if( !bFromFile )
  837.     {
  838.         UINT EffectLength = strEffect.GetLength();
  839.         char* strEffectA = new char[EffectLength + 1];
  840.         if( strEffectA == NULL )
  841.             return E_OUTOFMEMORY;
  842.         WideCharToMultiByte( CP_ACP, 0, strEffect, -1, strEffectA, EffectLength + 1, NULL, NULL );
  843.         
  844.         hr = D3DXCreateEffect( DXUTGetD3DDevice(), strEffectA, EffectLength, NULL, 
  845.                                &includeManager, dwFlags, NULL, &m_pEffect, &pBufferErrors );
  846.  
  847.         delete[] strEffectA;
  848.     }
  849.     else
  850.     {
  851.         hr = D3DXCreateEffectFromFile( DXUTGetD3DDevice(), strEffect, NULL, &includeManager, dwFlags, NULL, &m_pEffect, &pBufferErrors );
  852.     }
  853.  
  854.     if( pBufferErrors != NULL )
  855.         strErrors = (CHAR*)pBufferErrors->GetBufferPointer();
  856.     else
  857.         strErrors.Empty();
  858.  
  859.     SAFE_RELEASE( pBufferErrors );
  860.  
  861.     if( m_pEffect != NULL )
  862.     {
  863.         m_pEffect->GetDesc( &m_EffectDesc );
  864.  
  865.         ParseParameters( strErrors );
  866.  
  867.         // Look for UI elements
  868.         m_UIElements.InitEffectObjects( m_pEffect );
  869.  
  870.         if( m_EffectDesc.Techniques == 0 )
  871.             m_iTechnique = -1;
  872.         else if( (UINT)m_iTechnique >= m_EffectDesc.Techniques )
  873.             m_iTechnique = 0;
  874.         else if( m_iTechnique == -1 )
  875.             m_iTechnique = 0;
  876.         *piTechnique = m_iTechnique;
  877.  
  878.         for( UINT iTech = 0; iTech < m_EffectDesc.Techniques; iTech++ )
  879.         {
  880.             D3DXTECHNIQUE_DESC desc;
  881.             m_pEffect->GetTechniqueDesc( m_pEffect->GetTechnique( iTech ), &desc );
  882.             techniqueNameList.AddTail(desc.Name);
  883.         }
  884.     }
  885.  
  886.     if( strErrors.IsEmpty() )
  887.         strErrors = TEXT("Effect compilation successful\n");
  888.  
  889.     return hr;
  890. }
  891.  
  892.  
  893. HRESULT CRenderView::ParseParameters(CString &strErrors)
  894. {
  895.     HRESULT hr;
  896.     D3DXPARAMETER_DESC Desc;
  897.  
  898.     if( m_pEffect == NULL )
  899.         return E_FAIL;
  900.  
  901.     //look for background Texture
  902.     const char* pstrBackTexture;
  903.     SAFE_RELEASE( m_pBackgroundTexture );
  904.     if( NULL != m_pEffect->GetParameterByName( NULL, "BIMG" ) &&
  905.         SUCCEEDED( m_pEffect->GetParameterDesc( "BIMG", &Desc ) ) &&
  906.         Desc.Type == D3DXPT_STRING )
  907.     {
  908.         m_pEffect->GetString("BIMG", &pstrBackTexture);
  909.         WCHAR strBackTexture[MAX_PATH];
  910.         MultiByteToWideChar( CP_ACP, 0, pstrBackTexture, -1, strBackTexture, MAX_PATH );
  911.         TCHAR strPath[MAX_PATH];
  912.         EE_FindMediaFileCch( strPath, MAX_PATH, strBackTexture );
  913.         if( FAILED( hr = D3DXCreateTextureFromFile( DXUTGetD3DDevice(), strPath, &m_pBackgroundTexture) ) )
  914.         {
  915.             strErrors += TEXT("Could not load background image texture ");
  916.             strErrors += strBackTexture;
  917.             strErrors += TEXT("\n");
  918.         }
  919.     }
  920.     // look for background environment Texture
  921.     SAFE_RELEASE( m_pEnvironmentTexture );
  922.     if( NULL != m_pEffect->GetParameterByName( NULL, "Environment" ) &&
  923.         SUCCEEDED( m_pEffect->GetParameterDesc( "Environment", &Desc ) ) &&
  924.         Desc.Type == D3DXPT_STRING )
  925.     {
  926.         m_pEffect->GetString("Environment", &pstrBackTexture);
  927.         TCHAR strBackTexture[MAX_PATH];
  928.         MultiByteToWideChar( CP_ACP, 0, pstrBackTexture, -1, strBackTexture, MAX_PATH );
  929.         TCHAR strPath[MAX_PATH];
  930.         EE_FindMediaFileCch( strPath, MAX_PATH, strBackTexture );
  931.         if( FAILED( hr = D3DXCreateCubeTextureFromFile( DXUTGetD3DDevice(), strPath, &m_pEnvironmentTexture) ) )
  932.         {
  933.             strErrors += TEXT("Could not load environment cube texture ");
  934.             strErrors += strBackTexture;
  935.             strErrors += TEXT("\n");
  936.         }
  937.     }
  938.  
  939.     // Look at parameters for semantics and annotations that we know how to interpret
  940.     D3DXPARAMETER_DESC ParamDesc;
  941.     D3DXPARAMETER_DESC AnnotDesc;
  942.     D3DXHANDLE hParam;
  943.     D3DXHANDLE hAnnot;
  944.     TCHAR strPath[MAX_PATH];
  945.     LPDIRECT3DBASETEXTURE9 pTex = NULL;
  946.  
  947.     for( UINT iParam = 0; iParam < m_EffectDesc.Parameters; iParam++ )
  948.     {
  949.         LPCSTR pstrName = NULL;
  950.         LPCSTR pstrFunction = NULL;
  951.         LPCSTR pstrTarget = NULL;
  952.         LPCSTR pstrTextureType = NULL;
  953.         INT Width = D3DX_DEFAULT;
  954.         INT Height= D3DX_DEFAULT;
  955.         INT Depth = D3DX_DEFAULT;
  956.  
  957.         hParam = m_pEffect->GetParameter ( NULL, iParam );
  958.         m_pEffect->GetParameterDesc( hParam, &ParamDesc );
  959.         if( ParamDesc.Semantic != NULL && 
  960.             ( ParamDesc.Class == D3DXPC_MATRIX_ROWS || ParamDesc.Class == D3DXPC_MATRIX_COLUMNS ) )
  961.         {
  962.             if( _strcmpi( ParamDesc.Semantic, "world" ) == 0 )
  963.                 m_MatWorldEffectHandle = hParam;
  964.             else if( _strcmpi( ParamDesc.Semantic, "view" ) == 0 )
  965.                 m_MatViewEffectHandle = hParam;
  966.             else if( _strcmpi( ParamDesc.Semantic, "projection" ) == 0 )
  967.                 m_MatProjEffectHandle = hParam;
  968.             else if( _strcmpi( ParamDesc.Semantic, "worldview" ) == 0 )
  969.                 m_MatWorldViewEffectHandle = hParam;
  970.             else if( _strcmpi( ParamDesc.Semantic, "viewprojection" ) == 0 )
  971.                 m_MatViewProjEffectHandle = hParam;
  972.             else if( _strcmpi( ParamDesc.Semantic, "worldviewprojection" ) == 0 )
  973.                 m_MatWorldViewProjEffectHandle = hParam;
  974.         }
  975.  
  976.         if( ParamDesc.Semantic != NULL && 
  977.             ( ParamDesc.Class == D3DXPC_VECTOR ))
  978.         {
  979.             if( _strcmpi( ParamDesc.Semantic, "materialambient" ) == 0 )
  980.                 m_MaterialAmbientEffectHandle = hParam;
  981.             else if( _strcmpi( ParamDesc.Semantic, "materialdiffuse" ) == 0 )
  982.                 m_MaterialDiffuseEffectHandle = hParam;
  983.             else if( _strcmpi( ParamDesc.Semantic, "materialspecular" ) == 0 )
  984.                 m_MaterialSpecularEffectHandle = hParam;
  985.             else if( _strcmpi( ParamDesc.Semantic, "cameraposition" ) == 0 )
  986.                 m_VecCameraPosEffectHandle = hParam;
  987.         }
  988.  
  989.         if( ParamDesc.Semantic != NULL && 
  990.             ( ParamDesc.Class == D3DXPC_SCALAR ))
  991.         {
  992.             if( _strcmpi( ParamDesc.Semantic, "materialpower" ) == 0 )
  993.                 m_MaterialSpecularPowerEffectHandle = hParam;
  994.             else if( _strcmpi( ParamDesc.Semantic, "time" ) == 0 )
  995.                 m_TimeEffectHandle = hParam;
  996.             else if( _strcmpi( ParamDesc.Semantic, "meshradius" ) == 0 )
  997.                 m_MeshRadiusEffectHandle = hParam;
  998.         }
  999.  
  1000.         for( UINT iAnnot = 0; iAnnot < ParamDesc.Annotations; iAnnot++ )
  1001.         {
  1002.             hAnnot = m_pEffect->GetAnnotation ( hParam, iAnnot );
  1003.             m_pEffect->GetParameterDesc( hAnnot, &AnnotDesc );
  1004.             if( _strcmpi( AnnotDesc.Name, "name" ) == 0 )
  1005.                 m_pEffect->GetString( hAnnot, &pstrName );
  1006.             else if ( _strcmpi( AnnotDesc.Name, "function" ) == 0 )
  1007.                 m_pEffect->GetString( hAnnot, &pstrFunction );
  1008.             else if ( _strcmpi( AnnotDesc.Name, "target" ) == 0 )
  1009.                 m_pEffect->GetString( hAnnot, &pstrTarget );
  1010.             else if ( _strcmpi( AnnotDesc.Name, "width" ) == 0 )
  1011.                 m_pEffect->GetInt( hAnnot, &Width );
  1012.             else if ( _strcmpi( AnnotDesc.Name, "height" ) == 0 )
  1013.                 m_pEffect->GetInt( hAnnot, &Height );
  1014.             else if ( _strcmpi( AnnotDesc.Name, "depth" ) == 0 )
  1015.                 m_pEffect->GetInt( hAnnot, &Depth );
  1016.             else if( _strcmpi( AnnotDesc.Name, "type" ) == 0 )
  1017.                 m_pEffect->GetString( hAnnot, &pstrTextureType );
  1018.  
  1019.         }
  1020.         if( pstrName != NULL )
  1021.         {
  1022.             pTex = NULL;
  1023.             TCHAR strName[MAX_PATH];
  1024.             MultiByteToWideChar( CP_ACP, 0, pstrName, -1, strName, MAX_PATH );
  1025.             EE_FindMediaFileCch( strPath, MAX_PATH, strName );
  1026.             if (pstrTextureType != NULL) 
  1027.             {
  1028.                 if( _strcmpi( pstrTextureType, "volume" ) == 0 )
  1029.                 {
  1030.                     LPDIRECT3DVOLUMETEXTURE9 pVolumeTex = NULL;
  1031.                     if( SUCCEEDED( hr = D3DXCreateVolumeTextureFromFileEx( DXUTGetD3DDevice(), strPath, 
  1032.                         Width, Height, Depth, 1, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED,
  1033.                         D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &pVolumeTex ) ) )
  1034.                     {
  1035.                         pTex = pVolumeTex;
  1036.                     }
  1037.                     else
  1038.                     {
  1039.                         strErrors += TEXT("Could not load volume texture ");
  1040.                         strErrors += strName;
  1041.                         strErrors += TEXT("\n");
  1042.                     }
  1043.                 }
  1044.                 else if( _strcmpi( pstrTextureType, "cube" ) == 0 )
  1045.                 {
  1046.                     LPDIRECT3DCUBETEXTURE9 pCubeTex = NULL;
  1047.                     if( SUCCEEDED( hr = D3DXCreateCubeTextureFromFileEx( DXUTGetD3DDevice(), strPath, 
  1048.                         Width, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED,
  1049.                         D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &pCubeTex ) ) )
  1050.                     {
  1051.                         pTex = pCubeTex;
  1052.                     }
  1053.                     else
  1054.                     {
  1055.                         strErrors += TEXT("Could not load cube texture ");
  1056.                         strErrors += strName;
  1057.                         strErrors += TEXT("\n");
  1058.                     }
  1059.                 }
  1060.             }
  1061.             else
  1062.             {
  1063.                 LPDIRECT3DTEXTURE9 p2DTex = NULL;
  1064.                 if( SUCCEEDED( hr = D3DXCreateTextureFromFileEx( DXUTGetD3DDevice(), strPath, 
  1065.                     Width, Height, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED,
  1066.                     D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &p2DTex ) ) )
  1067.                 {
  1068.                     pTex = p2DTex;
  1069.                 }
  1070.                 else
  1071.                 {
  1072.                     strErrors += TEXT("Could not load texture ");
  1073.                     strErrors += strName;
  1074.                     strErrors += TEXT("\n");
  1075.                 }
  1076.             }
  1077.  
  1078.             // Apply successfully loaded texture to effect
  1079.             if( SUCCEEDED(hr) && pTex != NULL ) 
  1080.             {
  1081.                 m_pEffect->SetTexture( m_pEffect->GetParameter( NULL, iParam ), pTex );
  1082.                 SAFE_RELEASE( pTex );
  1083.             }
  1084.         }
  1085.         else if( pstrFunction != NULL )
  1086.         {
  1087.             LPD3DXBUFFER pFunction = NULL;
  1088.             LPD3DXTEXTURESHADER pTextureShader = NULL;
  1089.             CIncludeManager includeManager(this);
  1090.             CString strEffect = GetDocument()->GetCode();
  1091.             UINT EffectLength = strEffect.GetLength();
  1092.             char* strEffectA = new char[EffectLength + 1];
  1093.             if( strEffectA == NULL )
  1094.                 return E_OUTOFMEMORY;
  1095.             WideCharToMultiByte( CP_ACP, 0, strEffect, -1, strEffectA, EffectLength + 1, NULL, NULL );
  1096.  
  1097.             if( pstrTarget == NULL )
  1098.                 pstrTarget = "tx_1_0";
  1099.  
  1100.             LPD3DXBUFFER pBufferErrors = NULL;
  1101.             if( SUCCEEDED( hr = D3DXCompileShader( strEffectA, (UINT)strlen(strEffectA), NULL, 
  1102.                 &includeManager, pstrFunction, pstrTarget, 0, &pFunction, &pBufferErrors, NULL ) ) )
  1103.             {
  1104.                 if( SUCCEEDED( hr = D3DXCreateTextureShader((DWORD *)pFunction->GetBufferPointer(), &pTextureShader) ) )
  1105.                 {
  1106.                     pTextureShader->SetDefaults();
  1107.  
  1108.                     if( Width == D3DX_DEFAULT )
  1109.                         Width = 64;
  1110.                     if( Height == D3DX_DEFAULT )
  1111.                         Height = 64;
  1112.                     if( Depth == D3DX_DEFAULT )
  1113.                         Depth = 64;
  1114.  
  1115.                     if (pstrTextureType != NULL) 
  1116.                     {
  1117.                         if( _strcmpi( pstrTextureType, "volume" ) == 0 )
  1118.                         {
  1119.                             LPDIRECT3DVOLUMETEXTURE9 pVolumeTex = NULL;
  1120.                             if( SUCCEEDED( hr = D3DXCreateVolumeTexture( DXUTGetD3DDevice(), 
  1121.                                 Width, Height, Depth, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pVolumeTex) ) )
  1122.                             {
  1123.                                 if( SUCCEEDED( hr = D3DXFillVolumeTextureTX( pVolumeTex, pTextureShader ) ) ) 
  1124.                                     pTex = pVolumeTex;
  1125.                             }
  1126.                         }
  1127.                         else if( _strcmpi( pstrTextureType, "cube" ) == 0 )
  1128.                         {
  1129.                             LPDIRECT3DCUBETEXTURE9 pCubeTex = NULL;
  1130.                             if( SUCCEEDED( hr = D3DXCreateCubeTexture( DXUTGetD3DDevice(), 
  1131.                                 Width, D3DX_DEFAULT, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pCubeTex) ) )
  1132.                             {
  1133.                                 if( SUCCEEDED( hr = D3DXFillCubeTextureTX( pCubeTex, pTextureShader ) ) )
  1134.                                     pTex = pCubeTex;
  1135.                             }
  1136.                         }
  1137.                     }
  1138.                     else
  1139.                     {
  1140.                         LPDIRECT3DTEXTURE9 p2DTex = NULL;
  1141.                         if( SUCCEEDED( hr = D3DXCreateTexture( DXUTGetD3DDevice(), Width, Height, 
  1142.                             D3DX_DEFAULT, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &p2DTex) ) )
  1143.                         {
  1144.                             if( SUCCEEDED( hr = D3DXFillTextureTX( p2DTex, pTextureShader ) ) )
  1145.                                 pTex = p2DTex;
  1146.                         }
  1147.                     }
  1148.                     m_pEffect->SetTexture( m_pEffect->GetParameter( NULL, iParam ), pTex );
  1149.                     SAFE_RELEASE(pTex);
  1150.                     SAFE_RELEASE(pTextureShader);
  1151.                 }
  1152.                 SAFE_RELEASE(pFunction);
  1153.             }
  1154.             if( pBufferErrors != NULL )
  1155.             {
  1156.                 strErrors += (CHAR*)pBufferErrors->GetBufferPointer();
  1157.                 pBufferErrors->Release();
  1158.             }
  1159.  
  1160.             delete[] strEffectA;
  1161.         }
  1162.     }
  1163.  
  1164.     //look for background Color
  1165.     if( NULL != m_pEffect->GetParameterByName( NULL, "BCLR" ) &&
  1166.         SUCCEEDED( m_pEffect->GetParameterDesc( "BCLR", &Desc ) ) )
  1167.         m_pEffect->GetInt("BCLR", (INT *)&m_dwBackgroundColor);
  1168.     else
  1169.         m_dwBackgroundColor = D3DCOLOR_ARGB(255, 0, 0, 255);
  1170.  
  1171.  
  1172.     // look for mesh
  1173.     if( NULL != m_pEffect->GetParameterByName( NULL, "XFile" ) &&
  1174.         SUCCEEDED( m_pEffect->GetParameterDesc( "XFile", &Desc ) ) )
  1175.     {
  1176.         const char *fileName;
  1177.     
  1178.         m_pEffect->GetString("XFile",&fileName);
  1179.         if( _strcmpi( fileName, m_strMesh ) != 0 || m_pMesh == NULL )
  1180.         {
  1181.             UnloadMesh();
  1182.             strcpy( m_strMesh, fileName ); 
  1183.             
  1184.             //load the mesh
  1185.             LoadMesh( strErrors );
  1186.         }
  1187.     }
  1188.     else
  1189.     {
  1190.         if( strlen(m_strMesh) > 0 )
  1191.         {
  1192.             // There used to be an XFile, but no longer
  1193.             UnloadMesh();
  1194.             m_strMesh[0] = NULL;
  1195.         }
  1196.     }
  1197.     BOOL bUsesTangents = FALSE;
  1198.  
  1199.     // Look for tangents semantic
  1200.     D3DXEFFECT_DESC EffectDesc;
  1201.     D3DXHANDLE hTechnique;
  1202.     D3DXTECHNIQUE_DESC TechniqueDesc;
  1203.     D3DXHANDLE hPass;
  1204.     D3DXPASS_DESC PassDesc;
  1205.  
  1206.     m_pEffect->GetDesc( &EffectDesc );
  1207.     for( UINT iTech = 0; iTech < EffectDesc.Techniques; iTech++ )
  1208.     {
  1209.         hTechnique = m_pEffect->GetTechnique( iTech );
  1210.         m_pEffect->GetTechniqueDesc( hTechnique, &TechniqueDesc );
  1211.         for( UINT iPass = 0; iPass < TechniqueDesc.Passes; iPass++ )
  1212.         {
  1213.             hPass = m_pEffect->GetPass( hTechnique, iPass );
  1214.             m_pEffect->GetPassDesc( hPass, &PassDesc );
  1215.  
  1216.             UINT NumVSSemanticsUsed;
  1217.             D3DXSEMANTIC pVSSemantics[MAXD3DDECLLENGTH];
  1218.  
  1219.             if( !PassDesc.pVertexShaderFunction ||
  1220.                 FAILED( D3DXGetShaderInputSemantics( PassDesc.pVertexShaderFunction, pVSSemantics, &NumVSSemanticsUsed ) ) )
  1221.             {
  1222.                 continue;
  1223.             }
  1224.  
  1225.             for( UINT iSem = 0; iSem < NumVSSemanticsUsed; iSem++ )
  1226.             {
  1227.                 if( pVSSemantics[iSem].Usage == D3DDECLUSAGE_TANGENT )
  1228.                 {
  1229.                     bUsesTangents = TRUE;
  1230.                     goto DoneLooking;
  1231.                 }
  1232.             }
  1233.         }
  1234.     }
  1235.  
  1236. DoneLooking:
  1237.     if( bUsesTangents && m_pMesh != NULL )
  1238.     {
  1239.         D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE];
  1240.         D3DVERTEXELEMENT9 End = D3DDECL_END();
  1241.         int iElem;
  1242.      
  1243.         m_pMesh->GetDeclaration( Declaration );
  1244.      
  1245.         BOOL bHasTangents = FALSE;
  1246.         for( iElem=0; Declaration[iElem].Stream != End.Stream; iElem++ )
  1247.         {   
  1248.             if( Declaration[iElem].Usage == D3DDECLUSAGE_TANGENT )
  1249.             {
  1250.                 bHasTangents = TRUE;
  1251.                 break;
  1252.             }
  1253.         }
  1254.      
  1255.         // Update Mesh Semantics if changed
  1256.         if( !bHasTangents ) 
  1257.         {
  1258.             Declaration[iElem].Stream = 0;
  1259.             Declaration[iElem].Offset = (WORD)m_pMesh->GetNumBytesPerVertex();
  1260.             Declaration[iElem].Type = D3DDECLTYPE_FLOAT3;
  1261.             Declaration[iElem].Method = D3DDECLMETHOD_DEFAULT;
  1262.             Declaration[iElem].Usage = D3DDECLUSAGE_TANGENT;
  1263.             Declaration[iElem].UsageIndex = 0;
  1264.             Declaration[iElem+1] = End;
  1265.             LPD3DXMESH pTempMesh;
  1266.             hr = m_pMesh->CloneMesh( D3DXMESH_MANAGED, Declaration, DXUTGetD3DDevice(), &pTempMesh );
  1267.             if( SUCCEEDED( hr ) )
  1268.             {
  1269.                 SAFE_RELEASE( m_pMesh );
  1270.                 m_pMesh = pTempMesh;
  1271.                 hr = D3DXComputeTangent( m_pMesh, 0, 0, D3DX_DEFAULT, TRUE, NULL );
  1272.             }
  1273.         }
  1274.     }
  1275.  
  1276.     return S_OK;
  1277. }
  1278.  
  1279.  
  1280. HRESULT CRenderView::LoadMesh( CString &strErrors )
  1281. {
  1282.     if( strlen(m_strMesh) == 0 )
  1283.         return S_OK;
  1284.  
  1285.     LPDIRECT3DVERTEXBUFFER9 pVB = NULL;
  1286.     void*      pVertices = NULL;
  1287.     LPD3DXMESH pTempMesh;
  1288.     WCHAR      strMeshW[MAX_PATH];
  1289.     WCHAR      strMeshPath[MAX_PATH];
  1290.     HRESULT    hr;
  1291.     LPD3DXBUFFER pbufAdjacency;
  1292.  
  1293.     // Load the mesh from the specified file
  1294.     MultiByteToWideChar( CP_ACP, 0, m_strMesh, -1, strMeshW, MAX_PATH );
  1295.     if( FAILED( hr = EE_FindMediaFileCch( strMeshPath, MAX_PATH, strMeshW ) ) )
  1296.     {
  1297.         strErrors += L"Could not find XFile ";
  1298.         strErrors += strMeshW;
  1299.         strErrors += L"\n";
  1300.         return hr;
  1301.     }
  1302.  
  1303.     hr = D3DXLoadMeshFromX( strMeshPath, D3DXMESH_MANAGED, DXUTGetD3DDevice(), 
  1304.                             &pbufAdjacency, &m_pbufMaterials, NULL, &m_dwNumMaterials, 
  1305.                             &m_pMesh );
  1306.     if( FAILED(hr) )
  1307.     {
  1308.         SAFE_RELEASE(pbufAdjacency);
  1309.         strErrors += L"Could not load XFile ";
  1310.         strErrors += strMeshW;
  1311.         strErrors += L"\n";
  1312.         return hr;
  1313.     }
  1314.  
  1315.     // Initialize the mesh directory string
  1316.     WCHAR *pwszLastBSlash = wcsrchr( strMeshPath, L'\\' );
  1317.     if( pwszLastBSlash )
  1318.         *pwszLastBSlash = L'\0';
  1319.     else
  1320.         lstrcpyW( strMeshPath, L"." );
  1321.  
  1322.     hr = m_pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE, (DWORD*)pbufAdjacency->GetBufferPointer(), NULL, NULL, NULL);
  1323.     if ( FAILED(hr) )
  1324.     {
  1325.         SAFE_RELEASE(pbufAdjacency);
  1326.         return hr;
  1327.     }
  1328.  
  1329.     SAFE_RELEASE(pbufAdjacency);
  1330.  
  1331.     // Lock the vertex buffer, to generate a simple bounding sphere
  1332.     hr = m_pMesh->GetVertexBuffer( &pVB );
  1333.     if( FAILED(hr) )
  1334.         return hr;
  1335.  
  1336.     hr = pVB->Lock( 0, 0, &pVertices, 0 );
  1337.     if( FAILED(hr) )
  1338.     {
  1339.         SAFE_RELEASE( pVB );
  1340.         return hr;
  1341.     }
  1342.  
  1343.     hr = D3DXComputeBoundingSphere( (D3DXVECTOR3*)pVertices, m_pMesh->GetNumVertices(), 
  1344.                                     D3DXGetFVFVertexSize(m_pMesh->GetFVF()), &m_vObjectCenter, 
  1345.                                     &m_fObjectRadius );
  1346.     if( FAILED(hr) )
  1347.     {
  1348.         pVB->Unlock();
  1349.         SAFE_RELEASE( pVB );
  1350.         return hr;
  1351.     }
  1352.  
  1353.     // Adjust near/far clip planes of projection matrix based on the object radius
  1354.     const D3DSURFACE_DESC *pBackBufferSurfaceDesc = DXUTGetBackBufferSurfaceDesc();
  1355.     FLOAT fAspect = (FLOAT)pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height;
  1356.     D3DXMatrixPerspectiveFovLH( &m_matProj, D3DX_PI/4, fAspect, 
  1357.                                 m_fObjectRadius/64.0f, m_fObjectRadius*64.0f );
  1358.     DXUTGetD3DDevice()->SetTransform( D3DTS_PROJECTION, &m_matProj );
  1359.  
  1360.     m_ArcBallMesh.SetTranslationRadius( m_fObjectRadius );
  1361.     m_ArcBallView.SetTranslationRadius( m_fObjectRadius );
  1362.  
  1363.     if( 0 == m_dwNumMaterials )
  1364.     {
  1365.         pVB->Unlock();
  1366.         SAFE_RELEASE( pVB );
  1367.         return E_INVALIDARG;
  1368.     }
  1369.  
  1370.     // Get the array of materials out of the returned buffer, allocate a
  1371.     // texture array, and load the textures
  1372.     m_pMaterials = (D3DXMATERIAL*)m_pbufMaterials->GetBufferPointer();
  1373.     m_ppTextures = new LPDIRECT3DTEXTURE9[m_dwNumMaterials];
  1374.  
  1375.     // Change the current directory to the .x's directory so
  1376.     // that the search can find the texture files.
  1377.     WCHAR wszWorkingDir[MAX_PATH];
  1378.     GetCurrentDirectory( MAX_PATH, wszWorkingDir );
  1379.     wszWorkingDir[MAX_PATH - 1] = L'\0';
  1380.     SetCurrentDirectory( strMeshPath );
  1381.  
  1382.     for( UINT i=0; i<m_dwNumMaterials; i++ )
  1383.     {
  1384.         m_ppTextures[i] = NULL;
  1385.         TCHAR strTextureName[MAX_PATH];
  1386.         TCHAR strTexturePath[MAX_PATH] = _T("");
  1387.         if( m_pMaterials[i].pTextureFilename != NULL && strlen( m_pMaterials[i].pTextureFilename ) != 0 )
  1388.         {
  1389.             MultiByteToWideChar( CP_ACP, 0, m_pMaterials[i].pTextureFilename, -1, strTextureName, MAX_PATH );
  1390.             if( FAILED( hr = EE_FindMediaFileCch( strTexturePath, MAX_PATH, strTextureName ) ) )
  1391.             {
  1392.                 strErrors += TEXT("Could not find texture ");
  1393.                 strErrors += strTextureName;
  1394.                 strErrors += TEXT(" referenced by XFile ");
  1395.                 strErrors += strMeshW;
  1396.                 strErrors += TEXT("\n");
  1397.             }
  1398.             else if( FAILED( hr = D3DXCreateTextureFromFile( DXUTGetD3DDevice(), strTexturePath, &m_ppTextures[i] ) ) )
  1399.             {
  1400.                 strErrors += TEXT("Could not load texture ");
  1401.                 strErrors += strTextureName;
  1402.                 strErrors += TEXT(" referenced by XFile ");
  1403.                 strErrors += strMeshW;
  1404.                 strErrors += TEXT("\n");
  1405.             }
  1406.         }
  1407.     }
  1408.  
  1409.     SetCurrentDirectory( wszWorkingDir );
  1410.  
  1411.     pVB->Unlock();
  1412.     SAFE_RELEASE( pVB );
  1413.  
  1414.     // Make sure there are normals, which are required for the tesselation
  1415.     // enhancement
  1416.     if( !(m_pMesh->GetFVF() & D3DFVF_NORMAL) )
  1417.     {
  1418.         hr = m_pMesh->CloneMeshFVF( m_pMesh->GetOptions(), 
  1419.                                           m_pMesh->GetFVF() | D3DFVF_NORMAL, 
  1420.                                           DXUTGetD3DDevice(), &pTempMesh );
  1421.         if( FAILED(hr) )
  1422.             return hr;
  1423.  
  1424.         D3DXComputeNormals( pTempMesh, NULL );
  1425.  
  1426.         SAFE_RELEASE( m_pMesh );
  1427.         m_pMesh = pTempMesh;
  1428.     }
  1429.  
  1430.     return S_OK;
  1431. }
  1432.  
  1433.  
  1434. void CRenderView::UnloadMesh()
  1435. {
  1436.     for( UINT i = 0; i < m_dwNumMaterials; i++ )
  1437.         SAFE_RELEASE( m_ppTextures[i] );
  1438.     SAFE_DELETE_ARRAY( m_ppTextures );
  1439.     SAFE_RELEASE( m_pMesh );
  1440.     SAFE_RELEASE( m_pbufMaterials );
  1441.     m_dwNumMaterials = 0L;
  1442.     m_strMesh[0] = 0;
  1443. }
  1444.  
  1445. LRESULT CRenderView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
  1446. {
  1447.     // If this is a mouse message, we need to map the coordinates
  1448.     // to relative to the render window.
  1449.     if( WM_LBUTTONDOWN == message ||
  1450.         WM_LBUTTONDBLCLK == message ||
  1451.         WM_LBUTTONUP == message ||
  1452.         WM_MBUTTONDOWN == message ||
  1453.         WM_MBUTTONDBLCLK == message ||
  1454.         WM_MBUTTONUP == message ||
  1455.         WM_RBUTTONDOWN == message ||
  1456.         WM_RBUTTONDBLCLK == message ||
  1457.         WM_RBUTTONUP == message ||
  1458.         WM_XBUTTONDOWN == message ||
  1459.         WM_XBUTTONDBLCLK == message ||
  1460.         WM_XBUTTONUP == message ||
  1461.         WM_MOUSEMOVE == message ||
  1462.         WM_MOUSEWHEEL == message )
  1463.     {
  1464.         POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
  1465.         // Map point to parent's coordinates.
  1466.         ::MapWindowPoints( GetSafeHwnd(), DXUTGetHWND(), &pt, 1 );
  1467.         lParam = MAKELPARAM( pt.x, pt.y );
  1468.     }
  1469.  
  1470.     if( DXUTGetShowSettingsDialog() )
  1471.     {
  1472.         // Prevent reentrant
  1473.         static bool bProcessing;
  1474.  
  1475.         if( !bProcessing )
  1476.         {
  1477.             bProcessing = true;
  1478.             DXUTStaticWndProc( DXUTGetHWND(), message, wParam, lParam );
  1479.             bProcessing = false;
  1480.         }
  1481.     }
  1482.  
  1483.     switch( message )
  1484.     {
  1485.         case WM_LBUTTONDOWN:
  1486.         {
  1487.             POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
  1488.             BOOL bSetCapture;
  1489.             m_UIElements.HandleMouseDown( pt.x, pt.y, &bSetCapture );
  1490.             if( bSetCapture )
  1491.                 SetCapture();
  1492.             break;
  1493.         }
  1494.  
  1495.         case WM_MOUSEMOVE:
  1496.         {
  1497.             POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
  1498.             m_UIElements.HandleMouseMove( pt.x, pt.y );
  1499.             break;
  1500.         }
  1501.  
  1502.         case WM_LBUTTONUP:
  1503.         {
  1504.             m_UIElements.HandleMouseUp();
  1505.             break;
  1506.         }
  1507.     }
  1508.  
  1509.     if( !m_UIElements.IsDragging() )
  1510.     {
  1511.         UINT bControl;
  1512.         bControl = GetAsyncKeyState(VK_CONTROL) & 0x8000;
  1513.  
  1514.         // Pass mouse messages to the ArcBall so it can build internal matrices
  1515.         if (!bControl)
  1516.             m_ArcBallMesh.HandleMessages( GetSafeHwnd(), message, wParam, lParam );
  1517.         else
  1518.             m_ArcBallView.HandleMessages( GetSafeHwnd(), message, wParam, lParam );
  1519.     }
  1520.  
  1521.     return CFormView::WindowProc(message, wParam, lParam);
  1522. }
  1523.  
  1524. void CRenderView::ChangeDevice() 
  1525. {
  1526.     DXUTPause( true, true );
  1527.     DXUTSetShowSettingsDialog( !DXUTGetShowSettingsDialog() );
  1528.     DXUTPause( false, false );
  1529. }
  1530.  
  1531.  
  1532. void CRenderView::SetTechnique( int iTech, CString strTechName )
  1533. {
  1534.     CString str;
  1535.     str.Format( TEXT("Rendering using technique '%s'"), strTechName );
  1536.     m_iTechnique = iTech;
  1537.     GetDlgItem(IDC_RENDERTEXT)->SetWindowText( str );
  1538.     D3DXHANDLE hTechnique = m_pEffect->GetTechnique( m_iTechnique );
  1539.     m_pEffect->SetTechnique( hTechnique );
  1540.     m_bTechniqueValidValid = FALSE;
  1541. }
  1542.  
  1543.  
  1544. void CRenderView::SetPass( int iPass, CString strPassName )
  1545. {
  1546.     m_iPass = iPass;
  1547. }
  1548.  
  1549. void CRenderView::GetPassNameList( int iTech, CStringList& passNameList )
  1550. {
  1551.     passNameList.RemoveAll();
  1552.  
  1553.     if( m_pEffect == NULL )
  1554.         return;
  1555.  
  1556.     D3DXTECHNIQUE_DESC techniqueDesc;
  1557.     D3DXHANDLE hTech;
  1558.     hTech = m_pEffect->GetTechnique( iTech );
  1559.     m_pEffect->GetTechniqueDesc( hTech, &techniqueDesc );
  1560.     for( UINT iPass = 0; iPass < techniqueDesc.Passes; iPass++ )
  1561.     {
  1562.         D3DXPASS_DESC desc;
  1563.         m_pEffect->GetPassDesc( m_pEffect->GetPass( hTech, iPass ), &desc );
  1564.         passNameList.AddTail(desc.Name);
  1565.     }
  1566. }
  1567.  
  1568.  
  1569. void CRenderView::ResetCamera()
  1570. {
  1571.     m_ArcBallMesh.Reset();
  1572.     m_ArcBallMesh.SetTranslationRadius( m_fObjectRadius );
  1573.  
  1574.     m_ArcBallView.Reset();
  1575.     m_ArcBallView.SetTranslationRadius( m_fObjectRadius );
  1576. }
  1577.  
  1578.  
  1579. BOOL FileExists( CString& strPath )
  1580. {
  1581.     HANDLE file;
  1582.  
  1583.     file = CreateFile( (LPCTSTR)strPath, GENERIC_READ, FILE_SHARE_READ, NULL, 
  1584.                        OPEN_EXISTING, 0, NULL );
  1585.     if( INVALID_HANDLE_VALUE != file )
  1586.     {
  1587.         CloseHandle( file );
  1588.         return TRUE;
  1589.     }
  1590.     return FALSE;
  1591. }
  1592.  
  1593. HRESULT CRenderView::EE_FindMediaFileCb( TCHAR* szDestPath, int cbDest, TCHAR* strFilename )
  1594. {
  1595.     return EE_FindMediaFileCch( szDestPath, cbDest / sizeof(TCHAR), strFilename );
  1596.  
  1597. }
  1598.  
  1599. // 1. Look in same dir as effects file (EffectFileDir)
  1600. // 2. Look in EffectFileDir\Media
  1601. // 3. Look in EffectFileDir\..\Media
  1602. // 4. Look in usual DxUtil_FindMediaFile paths
  1603. HRESULT CRenderView::EE_FindMediaFileCch( TCHAR* szDestPath, int cchDest, TCHAR* strFilename )
  1604. {
  1605.     CString strDoc = GetDocument()->GetPathName();
  1606.     CString strDocT;
  1607.     int iChar = strDoc.ReverseFind( TEXT('\\') );
  1608.     if( iChar >= 0 )
  1609.     {
  1610.         strDoc = strDoc.Left( iChar );
  1611.  
  1612.         strDocT = strDoc + TEXT("\\") + strFilename;
  1613.         if( FileExists( strDocT) )
  1614.         {
  1615.             _tcsncpy( szDestPath, strDocT, cchDest );
  1616.             szDestPath[cchDest-1] = 0; // _tcsncpy doesn't NULL term if it runs out of space
  1617.             return S_OK;
  1618.         }
  1619.  
  1620.         strDocT = strDoc + TEXT("\\Media\\") + strFilename;
  1621.         if( FileExists( strDocT) )
  1622.         {
  1623.             _tcsncpy( szDestPath, strDocT, cchDest );
  1624.             szDestPath[cchDest-1] = 0; // _tcsncpy doesn't NULL term if it runs out of space
  1625.             return S_OK;
  1626.         }
  1627.  
  1628.         strDocT = strDoc + TEXT("\\..\\Media\\" + strFilename);
  1629.         if( FileExists( strDocT) )
  1630.         {
  1631.             _tcsncpy( szDestPath, strDocT, cchDest );
  1632.             szDestPath[cchDest-1] = 0; // _tcsncpy doesn't NULL term if it runs out of space
  1633.             return S_OK;
  1634.         }
  1635.     }
  1636.     return DXUTFindDXSDKMediaFileCch( szDestPath, cchDest, strFilename );
  1637. }
  1638.  
  1639.